import './LayoutData.scss'
import { v4 } from 'uuid'
import { useState, useRef } from 'react'
import GridLayout from 'react-grid-layout'
import { useEventEmitter, useMount, useSize } from 'ahooks'
import { Spin, Result, FloatButton, Tooltip, App, Dropdown, Button, Popconfirm } from "antd"

import { Http } from '../Utils/Api'
import { TemplateCommon } from './Common'
import { useRequest } from 'alova/client'
import { AdminRouter } from '../Config/default'
import SmallWindow from '../Page/Other/SmallWindow'
import { Encrypt, Decrypt } from '../Utils/IndexedDB'
import { LayoutDeftula } from '../Config/LayoutDeftula'
import { modelStore, drawerStore } from '../Config/zustand'
import { strOfurlParamsFunc, replaceNodeById, ColorCallBack } from '../Utils'


import {
    BorderlessTableOutlined,
    ApiOutlined,
    LayoutOutlined,
    ProductOutlined,
    SendOutlined,
    ClearOutlined,
    SelectOutlined,
    DeleteOutlined,
    AppstoreAddOutlined,
    SettingOutlined,
    SaveOutlined,
} from '@ant-design/icons'

const { port } = window.location

const DropdownSZtyle = {
    '--iconSize': '16px',
    '--iconFilter': 'drop-shadow(1px 1px 1px #262626)',
    '--fontSize': '16px',
    '--fontFamily': 'ShuHeiTi',
    '--fontWeight': 400,
    '--fontStyle': 'normal',
    '--fontFilter': 'drop-shadow(1px 1px 1px #262626)',
}

const optionsBtnList = [
    { uuid: 1, label: '边距设置', icon: <BorderlessTableOutlined /> },
    { uuid: 2, label: '接口设置', icon: <ApiOutlined /> },
    { uuid: 3, label: '激活布局', icon: <LayoutOutlined /> },
    { uuid: 7, label: '保存数据', icon: <SaveOutlined /> },
]

const TemplateRender = ({ item, smallWindow, apiData }) => {
    const { temp, model, config } = item
    const { type, smallWindow: smallWindowStatus, smallTitle,
        text, titleText, titleSize, titleColor, titleFamily, titleStyle, titleWeight,
        titleShadowX, titleShadowY, titleShadowS, titleShadowC,
        backColor, backColorDeg, backMargin, backPadding, backRadius, backShadow, background
    } = model

    console.log('模块类型', type)

    const TemplateComponent = TemplateCommon[temp]?.temp || ''

    if (smallWindowStatus) {
        return (
            <SmallWindow config={smallWindow} title={smallTitle}>
                {temp ?
                    <TemplateComponent mode={model} config={config} apiData={apiData} /> :
                    <div className='WaitingSelection'>未选择模板</div>
                }
            </SmallWindow>
        )
    } else {
        const textStyle = {
            color: titleColor,
            fontSize: titleSize,
            fontFamily: titleFamily,
            fontStyle: titleStyle,
            fontWeight: titleWeight,
            filter: `drop-shadow(${titleShadowX}px ${titleShadowY}px ${titleShadowS}px ${titleShadowC})`,
        }
        const backStyle = {
            background: background && ColorCallBack(backColor, backColorDeg),
            margin: backMargin,
            padding: backPadding,
            borderRadius: backRadius,
            boxShadow: backShadow,
        }

        return (
            <div className='OrdinaryModule' style={background ? backStyle : {}}>
                {text && <div className='OrdinaryModule__title' style={textStyle}>{titleText}</div>}
                <div className='OrdinaryModule__content'>
                    {temp ?
                        <TemplateComponent mode={model} config={config} apiData={apiData} /> :
                        <div className='WaitingSelection'>未选择模板</div>
                    }
                </div>
            </div>
        )
    }
}

const LayoutData = ({ page, smallWindow, router }) => {
    // console.log('当前页面', page)
    const { updateModel } = modelStore()
    const { updateDrawer } = drawerStore()
    const { message, modal, notification } = App.useApp()

    const gridRef = useRef(null)
    const size = useSize(gridRef)

    const PaddingEvent = useEventEmitter()
    const ApiUrlEvent = useEventEmitter()
    const PageLayoutEvent = useEventEmitter()
    const TemplateEvent = useEventEmitter()
    // console.log('当前路由', router)
    const [Open, setOpen] = useState(false)
    const [loading, setLoading] = useState(false)
    const [loadStu, setLoadStu] = useState(false)

    const [ApiData, setApiData] = useState([])
    const [Layout, setLayout] = useState({})
    const [LayoutData, setLayoutData] = useState([])
    const [LayoutStatus, setLayoutStatus] = useState(false)


    const { send } = useRequest(data => Http(data), { immediate: false })

    const getJson = () => {
        send({ method: 'get', url: 'dictionary/GetJsonInfoByUuid', params: { uuid: `StartConfig/${page}` } }).then(async res => {
            const data = await Decrypt(res)
            const { apiUrl, layout } = data
            setLayoutData(layout || [])
            getApiData(apiUrl || [])
            setLayout(data)
            setLoadStu(true)
            setLoading(true)
        }).catch(err => {
            setLoading(true)
        })
    }

    const setJson = async () => {
        console.log({ ...Layout, layout: LayoutData })
        const content = JSON.stringify(await Encrypt({ ...Layout, layout: LayoutData }))
        send({ method: 'post', url: 'dictionary/SaveJsonInfoByUuid', params: { uuid: `StartConfig/${page}`, content } }).then(res => {
            notification.success({ message: '数据请求成功!', description: '配置文件保存成功!', key: 'pageLayout' })
            getJson()
        }).catch(err => {
            notification.error({ message: '数据请求失败!', description: err.message, key: 'pageLayout' })
        })
    }

    const getAPIDate = async (data) => {
        const { method, url, apiData, path, params } = data
        try { return { name: apiData, data: await Http({ method, url, path, params: strOfurlParamsFunc(params) }) } }
        catch (err) { notification.error({ message: '数据请求失败!', description: err.message }) }
    }

    const getApiData = async (apiUrl) => {
        const apiData = await Promise.all(apiUrl.map(item => getAPIDate(item)))
        setApiData(apiData)
    }

    const onButtonClick = (uuid) => {
        switch (uuid) {
            case 1:
                updateDrawer({
                    type: 'AddFormData',
                    width: 480,
                    title: '边距设置',
                    mask: false,
                    data: { type: 'StartPadding', AddEvnet: PaddingEvent, Initial: Layout }
                })
                break;
            case 2:
                updateDrawer({
                    type: 'AddFormData',
                    width: 480,
                    title: '边距设置',
                    mask: false,
                    data: { type: 'StartApiUrl', AddEvnet: ApiUrlEvent, Initial: Layout }
                })
                break;
            case 3:
                message.loading({ content: '布局激活中...', duration: 0, key: 'pageLayout' })
                setLayoutStatus(true)
                break;
            case 7:
                setJson()
                break;
            default:
                break;
        }
    }

    const onAddItem = () => {
        const newItem = { i: v4(), x: 0, y: 0, w: 10, h: 10, temp: '', model: AdminRouter.LayoutModelConfig.model, config: {} }
        setLayoutData(e => ([...e, newItem]))
    }

    const onEndLayout = () => {
        message.success({ content: '布局已结束', key: 'pageLayout' })
        setLayoutStatus(false)
    }

    const onDelete = (i) => {
        const data = LayoutData.filter(v => v.i !== i)
        setLayoutData(data)
        notification.success({ message: '删除成功!', description: '模块信息已清除!', key: 'pageLayout' })
    }
    const onClear = () => {
        setLayoutData([])
        notification.success({ message: '清除成功!', description: '布局信息已清除!', key: 'pageLayout' })
    }

    const onChange = e => {
        const data = replaceFields(e, LayoutData)
        setLayoutData(data)
    }

    const replaceFields = (arr1, arr2) => {
        for (const item2 of arr2) {
            const foundIndex = arr1.findIndex(item1 => item1.i === item2.i)
            if (foundIndex !== -1) {
                if (item2.temp !== undefined) arr1[foundIndex].temp = item2.temp
                if (item2.model !== undefined) arr1[foundIndex].model = item2.model
                if (item2.config !== undefined) arr1[foundIndex].config = item2.config
            }
        }
        return arr1
    }

    const onSetModel = (i) => {
        updateDrawer({
            type: 'AddFormData',
            width: 480,
            title: '模块设置',
            mask: false,
            data: { type: 'LayoutSetModel', AddEvnet: PageLayoutEvent, Initial: LayoutData.find(v => v.i === i) }
        })
    }
    const onModelBack = (e) => {
        const { i, ...item } = e
        const arr = JSON.parse(JSON.stringify(LayoutData))
        const data = replaceNodeById(arr, i, item, 'i')
        setLayoutData([...data])
        notification.success({ message: '设置成功!', description: '模块信息设置成功!', key: 'pageLayout' })
    }

    const onSelectTemp = (i) => {
        updateModel({ type: 'CommonModel', width: 1200, title: '模块选择', data: { uuid: i, type: 'customModule', DateEvent: PageLayoutEvent } })
    }

    const onSelectTempBack = (data) => {
        const { uuid, name } = data
        LayoutData.find(v => v.i === uuid).temp = name
        LayoutData.find(v => v.i === uuid).config = name.includes('Chart') ? AdminRouter[name] : LayoutDeftula[name]
        setLayoutData([...LayoutData])
    }

    const onSetTemplate = (i) => {
        const { config, temp } = LayoutData.find(v => v.i === i)
        if (temp.includes('Chart')) {
            updateDrawer({
                type: 'CommonCharts',
                title: TemplateCommon[temp].title + '配置',
                width: 800,
                data: {
                    type: temp,
                    uuid: i,
                    Initial: config,
                    DateEvent: TemplateEvent
                }
            })
        } else {
            updateDrawer({
                type: 'AddFormData',
                width: 480,
                title: '模板设置',
                mask: false,
                data: {
                    type: 'SetTemplateConfig',
                    config: temp,
                    AddEvnet: TemplateEvent,
                    Initial: { ...config, uuid: i }
                }
            })
        }
    }

    const onSetTemplateBack = (data) => {
        const { uuid, ...config } = data
        LayoutData.find(v => v.i === uuid).config = config
        setLayoutData([...LayoutData])
        setJson()
    }

    const bodyItems = [
        { key: 0, type: 'group', label: '全局操作', },
        { key: 1, label: <Button style={DropdownSZtyle} type='link' icon={<AppstoreAddOutlined />} onClick={onAddItem}>新增模块</Button> },
        { key: 2, label: <Button style={DropdownSZtyle} type='link' icon={<SendOutlined />} onClick={onEndLayout}>结束布局</Button> },
        {
            key: 3,
            label: (
                <Popconfirm
                    title="清空警告"
                    description="确定清空当前布局吗？"
                    onConfirm={onClear}
                    okText="清空"
                    cancelText="取消"
                >
                    <Button style={DropdownSZtyle} type='link' icon={<ClearOutlined />} danger>清空布局</Button>
                </Popconfirm>
            )
        },
    ]
    const itemItems = (item) => {
        return ([
            { key: 0, type: 'group', label: '模块操作', },
            { key: 1, label: <Button style={DropdownSZtyle} type='link' icon={<SettingOutlined />} onClick={() => onSetModel(item.i)}>模块设置</Button> },
            { key: 2, label: <Button style={DropdownSZtyle} type='link' icon={<SelectOutlined />} onClick={() => onSelectTemp(item.i)}>模板选择</Button> },
            item.temp && { key: 3, label: <Button style={DropdownSZtyle} type='link' icon={<ProductOutlined />} onClick={() => onSetTemplate(item.i)}>模板设置</Button> },
            {
                key: 4,
                label: (
                    <Popconfirm
                        title="删除警告!"
                        description="确定要删除当前模块?"
                        onConfirm={() => onDelete(item.i)}
                        okText="删除"
                        cancelText="取消"
                    >
                        <Button style={DropdownSZtyle} type='link' icon={<DeleteOutlined />} danger > 删除模块</Button >
                    </Popconfirm>
                )
            },
        ].filter(v => v))
    }

    useMount(getJson)
    const CallBackFunc = (e) => {
        const { type, data } = e
        // console.log(type, data)
        const MapReturn = new Map([
            ['onFormBack', () => onModelBack(data)],
            ['onSelectTemp', () => onSelectTempBack(data)],
        ])
        const func = MapReturn.get(type)
        return func && func()
    }


    PageLayoutEvent.useSubscription(CallBackFunc)
    ApiUrlEvent.useSubscription(val => {
        if (val.type === 'onFormBack') {
            notification.success({ message: '设置成功!', description: '接口信息设置成功!', key: 'pageLayout' })
            setLayout(e => ({ ...e, ...val.data }))
        }
    })
    PaddingEvent.useSubscription(val => {
        if (val.type === 'onFormBack') {
            notification.success({ message: '设置成功!', description: '填充信息设置成功!', key: 'pageLayout' })
            setLayout(e => ({ ...e, ...val.data }))
        }
    })
    TemplateEvent.useSubscription(val => { if (val.type === 'onFormBack') onSetTemplateBack(val.data) })


    return (
        <div className='LayoutData' >
            {loading ?
                loadStu ?
                    <div
                        className='LayoutPage'
                        style={{ padding: `${Layout?.padding?.top}px ${Layout?.padding?.right}px ${Layout?.padding?.bottom}px ${Layout?.padding?.left}px` }}
                    >
                        <Dropdown menu={{ items: LayoutStatus ? bodyItems : [] }} trigger={['contextMenu']} placement='top'>
                            <div className='GridLayout' ref={gridRef} style={{ border: LayoutStatus ? '1px solid #eb2f96' : 'none' }} >
                                {size &&
                                    <GridLayout
                                        isDraggable={LayoutStatus}
                                        isResizable={LayoutStatus}
                                        layout={LayoutData}
                                        margin={[0, 0]}
                                        cols={24}
                                        rowHeight={size.height / 24}
                                        width={size.width}
                                        onDragStop={onChange}
                                        onResizeStop={onChange}
                                    >
                                        {LayoutData.map(item => {
                                            return (
                                                <div key={item.i} className='GridItem' style={LayoutStatus ? { border: `1px solid #ccc` } : {}}>
                                                    <Dropdown menu={{ items: LayoutStatus ? itemItems(item) : [] }} trigger={['contextMenu']} placement='bottom'>
                                                        <div className='GridTemp'>
                                                            <TemplateRender item={item} smallWindow={smallWindow} apiData={ApiData} />
                                                        </div>
                                                    </Dropdown>
                                                </div>
                                            )
                                        })}
                                    </GridLayout>
                                }
                            </div>
                        </Dropdown>
                    </div > :
                    <Result status="404" title={`当前页面 ${page} 开发中... `} /> :
                <Spin size="large" />
            }
            {
                port &&
                <FloatButton.Group
                    type="primary"
                    trigger="click"
                    shape="square"
                    open={Open}
                    onClick={e => setOpen(!Open)}
                    style={{ insetInlineEnd: 24 }}
                    icon={<SettingOutlined />}
                >
                    {optionsBtnList.map(item =>
                        <Tooltip key={item.uuid} title={item.label} placement="left">
                            <FloatButton icon={item.icon} onClick={() => onButtonClick(item.uuid)} />
                        </Tooltip>
                    )}
                </FloatButton.Group>
            }
        </div >
    );
};

export default LayoutData;

// https://jtgj-rest.ljkjkf.com/api/aiStats